package com.xy.xyaicpzs.service.impl;

import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.tea.TeaException;
import com.aliyun.teautil.models.RuntimeOptions;
import com.xy.xyaicpzs.service.SmsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 短信服务实现类
 */
@Service
public class SmsServiceImpl implements SmsService {
    
    private static final Logger logger = LoggerFactory.getLogger(SmsServiceImpl.class);
    
    @Value("${aliyun.sms.sign-name:西安精彩数据服务社}")
    private String signName;
    
    @Value("${aliyun.sms.template-code:SMS_489840017}")
    private String templateCode;
    
    @Value("${aliyun.sms.access-key-id}")
    private String accessKeyId;
    
    @Value("${aliyun.sms.access-key-secret}")
    private String accessKeySecret;
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    // 短信验证码Redis前缀
    private static final String SMS_CODE_PREFIX = "sms:code:";
    // 短信发送次数Redis前缀
    private static final String SMS_COUNT_PREFIX = "sms:count:";
    // 短信验证码有效期（分钟）
    private static final long SMS_CODE_EXPIRE = 5;
    // 每天最大发送次数
    private static final int MAX_SMS_COUNT_PER_DAY = 10;
    
    /**
     * 创建阿里云短信客户端
     */
    private Client createSmsClient() throws Exception {
        // 从配置文件中获取阿里云AccessKey配置
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config();
        config.accessKeyId = accessKeyId;
        config.accessKeySecret = accessKeySecret;
        config.endpoint = "dysmsapi.aliyuncs.com";
        return new Client(config);
    }
    
    /**
     * 生成6位随机数字验证码
     */
    private String generateVerificationCode() {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < 6; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }
    
    /**
     * 获取当天结束时间的剩余秒数
     */
    private long getSecondsUntilEndOfDay() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime endOfDay = now.toLocalDate().atTime(23, 59, 59);
        Duration duration = Duration.between(now, endOfDay);
        return duration.getSeconds();
    }
    
    @Override
    public boolean sendVerificationCode(String phoneNumber) throws Exception {
        // 检查当天发送次数是否达到上限
        String countKey = SMS_COUNT_PREFIX + phoneNumber + ":" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        Integer count = (Integer) redisTemplate.opsForValue().get(countKey);
        
        if (count != null && count >= MAX_SMS_COUNT_PER_DAY) {
            logger.warn("手机号{}今日短信发送次数已达上限: {}", phoneNumber, MAX_SMS_COUNT_PER_DAY);
            return false;
        }
        
        // 生成6位随机验证码
        String verificationCode = generateVerificationCode();
        
        // 构建短信请求
        Client client = createSmsClient();
        SendSmsRequest sendSmsRequest = new SendSmsRequest()
                .setSignName(signName)
                .setTemplateCode(templateCode)
                .setPhoneNumbers(phoneNumber)
                .setTemplateParam("{\"code\":\"" + verificationCode + "\"}");
        
        RuntimeOptions runtime = new RuntimeOptions();
        try {
            // 发送短信
            client.sendSmsWithOptions(sendSmsRequest, runtime);
            logger.info("短信验证码发送成功，手机号: {}", phoneNumber);
            
            // 将验证码保存到Redis，设置过期时间
            String codeKey = SMS_CODE_PREFIX + phoneNumber;
            redisTemplate.opsForValue().set(codeKey, verificationCode, SMS_CODE_EXPIRE, TimeUnit.MINUTES);
            
            // 增加当天发送次数，并设置过期时间为当天结束
            if (count == null) {
                count = 0;
            }
            redisTemplate.opsForValue().set(countKey, count + 1, getSecondsUntilEndOfDay(), TimeUnit.SECONDS);
            
            return true;
        } catch (TeaException error) {
            logger.error("短信发送失败, 手机号: {}, 错误信息: {}, 诊断信息: {}", 
                    phoneNumber, error.getMessage(), error.getData().get("Recommend"));
            return false;
        } catch (Exception error) {
            logger.error("短信发送异常, 手机号: {}", phoneNumber, error);
            return false;
        }
    }
    
    @Override
    public boolean verifyCode(String phoneNumber, String code) {
        if (phoneNumber == null || code == null) {
            return false;
        }
        
        String codeKey = SMS_CODE_PREFIX + phoneNumber;
        String savedCode = (String) redisTemplate.opsForValue().get(codeKey);
        
        if (savedCode != null && savedCode.equals(code)) {
            // 验证成功后删除验证码
            redisTemplate.delete(codeKey);
            return true;
        }
        
        return false;
    }
} 